Skip to content

release: buffers stack and string helpers (0.22.0)#61

Merged
tgiachi merged 11 commits into
mainfrom
develop
Jul 4, 2026
Merged

release: buffers stack and string helpers (0.22.0)#61
tgiachi merged 11 commits into
mainfrom
develop

Conversation

@tgiachi

@tgiachi tgiachi commented Jul 4, 2026

Copy link
Copy Markdown
Owner

Summary

Promotes develop to main for the 0.22.0 release:

  • SquidStd.Core.Buffers: single-threaded STArrayPool with monotonic trim clock and Gen2 trimming, ValueStringBuilder, RawInterpolatedStringHandler, PooledArraySpanFormattable (PR feat(core): buffers stack and string helpers ported from moongatev2 #60).
  • SquidStd.Core.Extensions.Strings: OrdinalStringHelpers (StartsWithOrdinal/EndsWithOrdinal and friends), InsensitiveStringHelpers, StringHelpers (Capitalize, Wrap, Remove/ReplaceAny with StringComparison, ToPooledArray, AppendSpaceWithArticle).
  • CollectionExtensions.AddNotNull, IpAddressExtensions.ToRawAddress.
  • New docs concepts article "Buffers and pooled strings".

Test plan

tgiachi added 11 commits July 4, 2026 17:06
…lock

Adapted from the moongatev2/.NET Foundation TLS array pool. Improvements
over the source: Environment.TickCount64 instead of DateTime.UtcNow for
trim timestamps, an internal TrimCore(milliseconds, pressure) seam for
deterministic tests, consistent local usage in Return, and full XML docs
including the single-threaded contract.
…docs

Changed class-level XML remarks from paramref (invalid for class-level parameters)
to plain code tag. CS1734 warning now cleared in Release builds.

Verified: dotnet build Release 0 errors, CS1734 gone (2 pre-existing warnings remain).
…pooled formattable

ValueStringBuilder and RawInterpolatedStringHandler are ported from the
.NET Foundation adaptations in moongatev2 (dual-pool mt switch kept, the
unsafe char* overload dropped). PooledArraySpanFormattable is a clean
rewrite with an explicit single-use TryFormat contract.
Clean-room implementations with the moongatev2 surface: StartsWithOrdinal,
EndsWithOrdinal and friends on strings and spans, Insensitive* mirrors,
plus Capitalize, Wrap, IndentMultiline, TrimMultiline, IndexOfTerminator,
Remove/ReplaceAny with StringComparison, ToPooledArray and
AppendSpaceWithArticle on ValueStringBuilder. Remove skips the full match
length and rejects small buffers with ArgumentException.
Covers STArrayPool vs ArrayPool.Shared guidance, the single-threaded
contract, trimming behavior, ValueStringBuilder usage and the string
helper families; links from the Core README.
Removes CollectionExtensions.RandomElement (collides with the existing
RandomExtensions family with contradictory empty-collection semantics),
makes ValueStringBuilder.Replace/ReplaceAny honor startIndex/count,
hardens the PooledArraySpanFormattable implicit string operator against
double pool returns, and aligns docs and the MIT header position.
feat(core): buffers stack and string helpers ported from moongatev2
"An incorrectly written provider said it implemented ICustomFormatter, and then didn't"
);

if (formatter?.Format(format, value, _provider) is string customFormatted)
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int IndexOfTerminator(this Span<byte> buffer, int sizeT)
=> ((ReadOnlySpan<byte>)buffer).IndexOfTerminator(sizeT);
[InlineData(new byte[] { 65, 66, 67 }, 1, -1)]
[InlineData(new byte[] { 65, 0, 0, 0, 66, 0 }, 2, 2)]
public void IndexOfTerminator_FindsNullTerminatorScaledBySize(byte[] buffer, int sizeT, int expected)
=> Assert.Equal(expected, ((ReadOnlySpan<byte>)buffer).IndexOfTerminator(sizeT));
Gen2GcCallback.Register(o => ((STArrayPool<T>)o).Trim(), this);
}

return _cacheBuckets = buckets;
Comment on lines +266 to +297
foreach (var word in text.Split(' ', StringSplitOptions.RemoveEmptyEntries))
{
var remaining = word.AsSpan();

while (!remaining.IsEmpty)
{
var separatorLength = current.Length == 0 ? 0 : 1;
var available = perLine - current.Length - separatorLength;

if (remaining.Length <= available)
{
current.Append(current.Length == 0 ? string.Empty : " ").Append(remaining);
remaining = default;
}
else if (current.Length == 0)
{
// Hard-break a word longer than a whole line.
current.Append(remaining[..perLine]);
remaining = remaining[perLine..];
}
else
{
lines.Add(current.ToString());
current.Clear();

if (lines.Count == maxLines)
{
return lines;
}
}
}
}
@tgiachi
tgiachi merged commit 1cbac18 into main Jul 4, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants